﻿using System;
using System.Reflection;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;

namespace Assist
{
	public class ExtensibleStorageManager
	{
		private static Schema CreateSchema(Document doc, Guid schemaGuid, object obj)
		{
			Schema schema = Schema.Lookup(schemaGuid);
			if (schema == null)
			{
				Transaction transaction = new Transaction(doc, "CreateSchema");
				try
				{
					transaction.Start();
					SchemaBuilder schemaBuilder = new SchemaBuilder(schemaGuid);
					Type type = obj.GetType();
					schemaBuilder.SetSchemaName(type.Name);
					foreach (PropertyInfo propertyInfo in type.GetProperties())
					{
						Type propertyType = propertyInfo.PropertyType;
						schemaBuilder.AddSimpleField(propertyInfo.Name, propertyType);
					}
					schema = schemaBuilder.Finish();
					transaction.Commit();
				}
				catch
				{
					transaction.RollBack();
				}
			}
			return schema;
		}

		public static void WriteToElement(Element elem, Guid schemaGuid, object obj)
		{
			Document document = elem.Document;
			Schema.Lookup(schemaGuid);
			Transaction transaction = new Transaction(document, "WriteExtensibleStorage");
			Schema schema = ExtensibleStorageManager.CreateSchema(document, schemaGuid, obj);
			if (schema != null && schema.SchemaName == obj.GetType().Name)
			{
				try
				{
					transaction.Start();
					Entity entity = new Entity(schema);
					foreach (PropertyInfo propertyInfo in obj.GetType().GetProperties())
					{
						Field field = schema.GetField(propertyInfo.Name);
						object value = propertyInfo.GetValue(obj, null);
						Type propertyType = propertyInfo.PropertyType;
						if (propertyType.Name == "String")
						{
							entity.Set<string>(field, (string)value);
						}
						else if (propertyType.Name == "Int32")
						{
							entity.Set<int>(field, (int)value);
						}
						else if (propertyType.Name == "Double")
						{
							entity.Set<double>(field, (double)value);
						}
						else if (propertyType.Name == "Boolean")
						{
							entity.Set<bool>(field, (bool)value);
						}
					}
					elem.SetEntity(entity);
					transaction.Commit();
				}
				catch
				{
					transaction.RollBack();
				}
			}
		}

		public static T ReadFromElement<T>(Element elem, Guid schemaGuid)
		{
			T t = (T)((object)Activator.CreateInstance(typeof(T)));
			Document document = elem.Document;
			Schema schema = Schema.Lookup(schemaGuid);
			if (schema != null && schema.SchemaName == typeof(T).Name)
			{
				try
				{
					Entity entity = elem.GetEntity(Schema.Lookup(schemaGuid));
					if (entity != null)
					{
						foreach (PropertyInfo propertyInfo in t.GetType().GetProperties())
						{
							Field field = schema.GetField(propertyInfo.Name);
							Type propertyType = propertyInfo.PropertyType;
							if (propertyType.Name == "String")
							{
								string value = entity.Get<string>(field);
								propertyInfo.SetValue(t, value, null);
							}
							else if (propertyType.Name == "Int32")
							{
								int num = entity.Get<int>(field);
								propertyInfo.SetValue(t, num, null);
							}
							else if (propertyType.Name == "Double")
							{
								double num2 = entity.Get<double>(field);
								propertyInfo.SetValue(t, num2, null);
							}
							else if (propertyType.Name == "Boolean")
							{
								bool flag = entity.Get<bool>(field);
								propertyInfo.SetValue(t, flag, null);
							}
						}
					}
				}
				catch
				{
				}
			}
			return t;
		}
	}
}
